home *** CD-ROM | disk | FTP | other *** search
/ Space & Astronomy / Space and Astronomy (October 1993).iso / mac / VIEWERS / X11 / XLOADIMG.TAR / zio.c < prev    next >
C/C++ Source or Header  |  1991-05-20  |  6KB  |  288 lines

  1. /* zio.c:
  2.  *
  3.  * this properly opens and reads from an image file, compressed or otherwise.
  4.  *
  5.  * jim frost 10.03.89
  6.  *
  7.  * this was hacked on 09.12.90 to cache reads and to use stdin.
  8.  *
  9.  * Copyright 1989, 1990 Jim Frost.  See included file "copyright.h" for
  10.  * complete copyright information.
  11.  */
  12.  
  13. #include "copyright.h"
  14. #include "image.h"
  15.  
  16. #ifdef VMS
  17. #define NO_UNCOMPRESS /* VMS doesn't have uncompress */
  18. #endif
  19.  
  20. #define MAX_ZFILES 32
  21.  
  22. static ZFILE ZFileTable[MAX_ZFILES];
  23.  
  24. /* read some info through the read cache
  25.  */
  26.  
  27. static int doRead(zf, buf, len)
  28.      ZFILE *zf;
  29.      byte *buf;
  30.      int len;
  31. { int bread, readlen;
  32.  
  33.   /* loop through the read
  34.    */
  35.  
  36.   for (bread= 0; bread < len; bread += readlen, zf->bufptr += readlen) {
  37.  
  38.     /* read new or move to next data block if necessary
  39.      */
  40.  
  41.     if (!zf->dataptr || (zf->bufptr == zf->dataptr->len)) {
  42.  
  43.       if (zf->dataptr && zf->dataptr->next)
  44.     zf->dataptr= zf->dataptr->next;
  45.       else {
  46.     if (!zf->dataptr) {
  47.  
  48.       /* if the reader told us to stop caching, just do the read.
  49.        */
  50.  
  51.       if (zf->nocache)
  52.         return(fread(zf->dataptr->buf, 1, BUFSIZ, zf->stream));
  53.       zf->data= zf->dataptr= (struct cache *)lmalloc(sizeof(struct cache));
  54.     }
  55.     else {
  56.       zf->dataptr->next= (struct cache *)lmalloc(sizeof(struct cache));
  57.       zf->dataptr= zf->dataptr->next;
  58.     }
  59.     zf->dataptr->next= NULL;
  60.     zf->dataptr->len= fread(zf->dataptr->buf, 1, BUFSIZ, zf->stream);
  61.     if (zf->dataptr->len < 0) {
  62.       perror("fread");
  63.       exit(1);
  64.     }
  65.       }
  66.       zf->bufptr= 0;
  67.     }
  68.  
  69.     /* calculate length we can get out of read buffer
  70.      */
  71.  
  72.     readlen= (len - bread > zf->dataptr->len - zf->bufptr ?
  73.           zf->dataptr->len - zf->bufptr : len - bread);
  74.     if (!readlen) /* we're at EOF */
  75.       return(bread);
  76.     bcopy(zf->dataptr->buf + zf->bufptr, buf + bread, readlen);
  77.   }
  78.   return(bread);
  79. }
  80.  
  81. /* reset a read cache
  82.  */
  83.  
  84. void zreset(filename)
  85.      char *filename;
  86. { int a;
  87.   struct cache *old;
  88.  
  89.   /* if NULL filename, reset the entire table
  90.    */
  91.  
  92.   if (!filename) {
  93.     for (a= 0; a < MAX_ZFILES; a++)
  94.       if (ZFileTable[a].filename)
  95.     zreset(ZFileTable[a].filename);
  96.     return;
  97.   }
  98.  
  99.   for (a= 0; a < MAX_ZFILES; a++)
  100.     if (ZFileTable[a].filename && !strcmp(filename, ZFileTable[a].filename))
  101.       break;
  102.  
  103.   if (a == MAX_ZFILES) /* no go joe */
  104.     return;
  105.  
  106.   if (ZFileTable[a].dataptr != ZFileTable[a].data)
  107.     fprintf(stderr, "zreset: warning: ZFILE for %s was not closed properly\n",
  108.        ZFileTable[a].filename);
  109.   while (ZFileTable[a].data) {
  110.     old= ZFileTable[a].data;
  111.     ZFileTable[a].data= ZFileTable[a].data->next;
  112.     free(old);
  113.   }
  114.   lfree((byte *)ZFileTable[a].filename);
  115.   ZFileTable[a].filename= NULL;
  116.   ZFileTable[a].dataptr= NULL;
  117.   ZFileTable[a].bufptr= 0;
  118.   ZFileTable[a].nocache= 0;
  119.  
  120.   switch(ZFileTable[a].type) {
  121.   case ZSTANDARD:
  122.     fclose(ZFileTable[a].stream);
  123.     break;
  124. #ifndef NO_UNCOMPRESS
  125.   case ZPIPE:
  126.     pclose(ZFileTable[a].stream);
  127.     break;
  128. #endif /* NO_UNCOMPRESS */
  129.   case ZSTDIN:
  130.     break;
  131.   default:
  132.     fprintf(stderr, "zreset: bad ZFILE structure\n");
  133.     exit(1);
  134.   }
  135. }
  136.  
  137. ZFILE *zopen(name)
  138.      char *name;
  139. { int    a;
  140.   ZFILE *zf;
  141.   char   buf[BUFSIZ];
  142.  
  143.   /* look for filename in open file table
  144.    */
  145.  
  146.   for (a= 0; a < MAX_ZFILES; a++)
  147.     if (ZFileTable[a].filename && !strcmp(name, ZFileTable[a].filename)) {
  148.  
  149.       /* if we try to reopen a file whose caching was disabled, warn the user
  150.        * and try to recover.  we cannot recover if it was stdin.
  151.        */
  152.  
  153.       if (ZFileTable[a].nocache) {
  154.     if (ZFileTable[a].type == ZSTDIN) {
  155.       fprintf(stderr, "zopen: caching was disabled by previous caller; can't reopen stdin\n");
  156.       return(NULL);
  157.     }
  158.     fprintf(stderr, "zopen: warning: caching was disabled by previous caller\n");
  159.     zreset(ZFileTable[a].filename);
  160.     break;
  161.       }
  162.       if (ZFileTable[a].dataptr != ZFileTable[a].data)
  163.     fprintf(stderr, "zopen: warning: file doubly opened\n");
  164.       ZFileTable[a].dataptr= ZFileTable[a].data;
  165.       ZFileTable[a].bufptr= 0;
  166.       return(ZFileTable + a);
  167.     }
  168.  
  169.   /* find open ZFileTable entry
  170.    */
  171.  
  172.   for (a= 0; (a < MAX_ZFILES) && ZFileTable[a].filename; a++)
  173.     /* EMPTY */
  174.     ;
  175.  
  176.   if (a == MAX_ZFILES) {
  177.     fprintf(stderr, "zopen: no more files available\n");
  178.     exit(1);
  179.   }
  180.   zf= ZFileTable + a;
  181.  
  182.   zf->filename= dupString(name);
  183.   zf->dataptr= NULL;
  184.   zf->bufptr= 0;
  185.   zf->nocache= 0;
  186.  
  187.   /* file filename is `stdin' then use stdin
  188.    */
  189.  
  190.   if (!strcmp(name, "stdin")) {
  191.     zf->type= ZSTDIN;
  192.     zf->stream= stdin;
  193.     return(zf);
  194.   }
  195.  
  196. #ifndef NO_UNCOMPRESS
  197.   /* if filename ends in `.Z' then open pipe to uncompress.  if your
  198.    * system doesn't have uncompress you can define NO_UNCOMPRESS and
  199.    * it just won't check for this.
  200.    */
  201.  
  202.   if ((strlen(name) > 2) && !strcmp(".Z", name + (strlen(name) - 2))) {
  203.     zf->type= ZPIPE;
  204.     sprintf(buf, "uncompress -c %s", name);
  205.     if (! (zf->stream= popen(buf, "r"))) {
  206.     lfree(zf->filename);
  207.     zf->filename= NULL;
  208.     return(NULL);
  209.     }
  210.     return(zf);
  211.   }
  212. #endif
  213.  
  214.   /* default to normal stream
  215.    */
  216.  
  217.   zf->type= ZSTANDARD;
  218.   if (!
  219. #ifdef VMS
  220.       (zf->stream= fopen(name, "r", "ctx=bin", "ctx=stm", "rfm=stmlf"))
  221. #else
  222.       (zf->stream= fopen(name, "r"))
  223. #endif
  224.       ) {
  225.     lfree(zf->filename);
  226.     zf->filename= NULL;
  227.     return(NULL);
  228.   }
  229.   return(zf);
  230. }
  231.  
  232. int zread(zf, buf, len)
  233.      ZFILE        *zf;
  234.      byte         *buf;
  235.      unsigned int  len;
  236. {
  237.   return(doRead(zf, buf, len));
  238. }
  239.  
  240. int zgetc(zf)
  241.      ZFILE *zf;
  242. { unsigned char c;
  243.  
  244.   if (doRead(zf, &c, 1) > 0)
  245.     return(c);
  246.   else
  247.     return(EOF);
  248. }
  249.  
  250. char *zgets(buf, size, zf)
  251.      byte         *buf;
  252.      unsigned int  size;
  253.      ZFILE        *zf;
  254. { int p= 0;
  255.  
  256.   while (doRead(zf, buf + p, 1) > 0) {
  257.     if (p == size)
  258.       return((char *)buf);
  259.     if (*(buf + p) == '\n') {
  260.       *(buf + p + 1)= '\0';
  261.       return((char *)buf);
  262.     }
  263.     p++;
  264.   }
  265.   return(NULL);
  266. }
  267.  
  268. /* this turns off caching when an image has been identified and we will not
  269.  * need to re-open it
  270.  */
  271.  
  272. void znocache(zf)
  273.      ZFILE *zf;
  274. {
  275.   zf->nocache= 1;
  276. }
  277.  
  278. /* reset cache pointers in a ZFILE.  nothing is actually reset until a
  279.  * zreset() is called with the filename.
  280.  */
  281.  
  282. void zclose(zf)
  283.      ZFILE *zf;
  284. {
  285.   zf->dataptr= zf->data;
  286.   zf->bufptr= 0;
  287. }
  288.